﻿/*****************************************介绍*****************************************
 * 作者：User
 * 创建时间：2025-09-09 16:13:20
 * 功能：界面【GamePanel】的View
        1、负责收集所有控件
        2、生成地图
**************************************************************************************/

using DG.Tweening;
using Game.Framework;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Game.UI.GamePanel
{
    public class GamePanelView : BasePanel
    {
        public const string PANEL_KEY = "Game_UI_GamePanel_GamePanel_Key";
        private const int m_Space = 2;
        private UILineRenderer m_LineRenderer;
        [SerializeField] RectOffset m_Padding;
        private GameDataModel.Level m_Level;
        private List<Item> m_Items;
        private RectTransform m_UILayout;
        private Item m_SelectedItem;
        private PathFinder m_PathFinder;
        private List<Vector2> m_Path;
        private Toggle m_PauseBtn;
        private Item m_Hint1, m_Hint2;
        private Guide m_Guide;

        protected override void RegistAny()
        {
            PanelManager.Instance.RegistPanel(PANEL_KEY, this);
            EventCenter.Instance.AddEventListen<long, long>(GameEventName.OnPlayerCoinsChanged, OnPlayerCoinsChanged);
            EventCenter.Instance.AddEventListen<int>(GameEventName.OnHintCountChanged, OnHintCountChanged);
            EventCenter.Instance.AddEventListen<int>(GameEventName.OnBombCountChanged, OnBombCountChanged);
            EventCenter.Instance.AddEventListen<int>(GameEventName.OnShuffleCountChanged, OnShuffleCountChanged);
            EventCenter.Instance.AddEventListen<int>(GameEventName.OnAddTimeCountChanged, OnAddTimeCountChanged);
            PoolManager.Instance.CreatePool(GamePanelNotifications.ITEM_POOL, GetRect(GamePanelNotifications.Item_RECT).gameObject, 64);
            PoolManager.Instance.CreatePool(GamePanelNotifications.BOMB_ITEM_POOL, GetRect(GamePanelNotifications.BombAnim_RECT).gameObject, 4);
        }

        protected override void UnregistAny()
        {
            PanelManager.Instance.UnregistPanel(PANEL_KEY);
            EventCenter.Instance.RemoveEventListen<long, long>(GameEventName.OnPlayerCoinsChanged, OnPlayerCoinsChanged);
            EventCenter.Instance.RemoveEventListen<int>(GameEventName.OnHintCountChanged, OnHintCountChanged);
            EventCenter.Instance.RemoveEventListen<int>(GameEventName.OnBombCountChanged, OnBombCountChanged);
            EventCenter.Instance.RemoveEventListen<int>(GameEventName.OnShuffleCountChanged, OnShuffleCountChanged);
            EventCenter.Instance.RemoveEventListen<int>(GameEventName.OnAddTimeCountChanged, OnAddTimeCountChanged);
            PoolManager.Instance.ClearPool(GamePanelNotifications.ITEM_POOL);
            PoolManager.Instance.ClearPool(GamePanelNotifications.BOMB_ITEM_POOL);
        }

        protected override void InitUI()
        {
            m_LineRenderer = GetRect(GamePanelNotifications.LineRenderer_RECT).GetComponent<UILineRenderer>();
            m_UILayout = GetRect(GamePanelNotifications.GameArea_RECT);
            m_Items = new List<Item>();
            m_Path = new List<Vector2>();
            m_PathFinder = new PathFinder();
            m_PauseBtn = GetControl<Toggle>(GamePanelNotifications.PauseBtn_CTRL);
            m_Guide = new Guide(this, m_Items);
        }

        private void OnPlayerCoinsChanged(long old, long now)
        {
            DOTween.To(() => old, x => GetControl<Text>(GamePanelNotifications.CoinNum_CTRL).text = $"{x}", now, 1f);
        }

        private void OnHintCountChanged(int count)
        {
            GetControl<Text>(GamePanelNotifications.HintNum_CTRL).text = count.ToString();
            GetControl<Text>(GamePanelNotifications.HintNum_CTRL).transform.parent.gameObject.SetActive(count > 0);
        }

        private void OnBombCountChanged(int count)
        {
            GetControl<Text>(GamePanelNotifications.BombNum_CTRL).text = count.ToString();
            GetControl<Text>(GamePanelNotifications.BombNum_CTRL).transform.parent.gameObject.SetActive(count > 0);
        }

        private void OnShuffleCountChanged(int count)
        {
            GetControl<Text>(GamePanelNotifications.ShuffleNum_CTRL).text = count.ToString();
            GetControl<Text>(GamePanelNotifications.ShuffleNum_CTRL).transform.parent.gameObject.SetActive(count > 0);
        }

        private void OnAddTimeCountChanged(int count)
        {
            GetControl<Text>(GamePanelNotifications.AddTimeNum_CTRL).text = count.ToString();
            GetControl<Text>(GamePanelNotifications.AddTimeNum_CTRL).transform.parent.gameObject.SetActive(count > 0);
        }

        // 剩余生命次数发生变化时处理
        private void OnLifeCountChanged(int remainLifeCount)
        {
            GetControl<Image>(GamePanelNotifications.Star_CTRL).DOFillAmount(0.273f * remainLifeCount + 0.0905f * (remainLifeCount - 1), .5f);
            // 如果扣完，直接死亡
            if (remainLifeCount <= 0)
            {
                UIUtility.DisplayPanel(LevelFailurePanel.LevelFailurePanelView.PANEL_KEY, "UI/LevelFailurePanel/Prefabs/LevelFailurePanel", data: this);
            }
        }

        public override void Init(object data)
        {
            m_Level = (GameDataModel.Level)data;
            m_IsPlayedMusic = false;

            // 处理状态
            if (m_Level.status != ELevelStatus.InProcess && m_Level.status != ELevelStatus.Completed)
                m_Level.status = ELevelStatus.InProcess;

            // 处理背景，暂时只有图片
            var bg = GetControl<Image>(GamePanelNotifications.ImgBg_CTRL);
            // 默认图片
            Sprite sprite = null;
            if (m_Level.assetsInfo == null || m_Level.finalSelectIdx == -1)
                sprite = AssetCacheServer.Instance.GetDefaultBg();
            else
            {
                var info = m_Level.assetsInfo[m_Level.finalSelectIdx];
                sprite = AssetCacheServer.Instance.GetSprite(info.type, info.id, true);
                if (!sprite)
                    sprite = AssetCacheServer.Instance.GetDefaultBg();
            }
            bg.sprite = sprite;
            var size = UIUtility.CalcSizeToFill(transform as RectTransform, bg.sprite.texture);
            bg.rectTransform.sizeDelta = new Vector2(size.width, size.height);

            OnPlayerCoinsChanged(0, GameDataMgr.Instance.TotalCoinsNum);
            if (GameDataMgr.Instance.IsUnlockErrorLimit())
            {
                EventCenter.Instance.AddEventListen<int>(GameEventName.OnLifeCountChanged, OnLifeCountChanged);
                OnLifeCountChanged(m_Level.lifeRemainNum);
            }
            GetControl<Image>(GamePanelNotifications.Star_CTRL).transform.parent.gameObject.SetActive(GameDataMgr.Instance.IsUnlockErrorLimit());

            GetControl<Text>(GamePanelNotifications.Time_CTRL).transform.parent.gameObject.SetActive(GameDataMgr.Instance.IsUnlockTimeLimit());

            GetControl<Text>(GamePanelNotifications.Level_CTRL).text = $"{BaseDataMgr.Instance.GetLanguageValue("Level")} {m_Level.level}";

            // 道具状态
            GetControl<Button>(GamePanelNotifications.HintBtn_CTRL).interactable = GameDataMgr.Instance.IsUnlockHint();
            GetControl<Button>(GamePanelNotifications.BombBtn_CTRL).interactable = GameDataMgr.Instance.IsUnlockBomb();
            GetControl<Button>(GamePanelNotifications.ShuffleBtn_CTRL).interactable = GameDataMgr.Instance.IsUnlockShuffle();
            GetControl<Button>(GamePanelNotifications.AddTimeBtn_CTRL).interactable = GameDataMgr.Instance.IsUnlockTime();

            OnHintCountChanged(GameDataMgr.Instance.HintRemainCount);
            OnBombCountChanged(GameDataMgr.Instance.BombRemainCount);
            OnShuffleCountChanged(GameDataMgr.Instance.ShuffleRemainCount);
            OnAddTimeCountChanged(GameDataMgr.Instance.AddTimeRemainCount);

            // 创建按格子
            StartCoroutine(DelayCreateItem());
        }

        protected override void ClickBtnHandle(string name)
        {
            switch (name)
            {
                case GamePanelNotifications.HintBtn_CTRL:
                    LogManager.Log($"高亮显示可消除格子");
                    if (GameDataMgr.Instance.HintRemainCount > 0 && Hint())
                        GameDataMgr.Instance.HintRemainCount = GameDataMgr.Instance.HintRemainCount - 1;
                    else
                        UIUtility.DisplayPanel(HintPanle.HintPanleView.PANEL_KEY, "UI/Item/HintPanle/Prefabs/HintPanel", data: this);
                    break;
                case GamePanelNotifications.BombBtn_CTRL:
                    LogManager.Log($"炸掉周围4个格子");
                    if (GameDataMgr.Instance.BombRemainCount > 0)
                    {
                        var itemIds = m_Level.Bomb();
                        if (itemIds.Count > 0)
                        {
                            foreach (var item in itemIds)
                                ShowBombEff(m_Items[item]);
                            //m_Items[item].UpdateUIStatus();
                            GameDataMgr.Instance.BombRemainCount = GameDataMgr.Instance.BombRemainCount - 1;
                        }
                    }
                    else
                        UIUtility.DisplayPanel(BombPanel.BombPanelView.PANEL_KEY, "UI/Item/BombPanel/Prefabs/BombPanel", data: this);
                    break;
                case GamePanelNotifications.ShuffleBtn_CTRL:
                    LogManager.Log($"刷新");
                    if (GameDataMgr.Instance.ShuffleRemainCount > 0)
                    {
                        GameDataMgr.Instance.ShuffleRemainCount = GameDataMgr.Instance.ShuffleRemainCount - 1;
                        UIUtility.SetGlobalInteractive(false);
                        var shuffles = m_Level.ShuffleUnlockedItems();
                        for (int i = 0; i < shuffles.Count; i++)
                            LogManager.Log($"{shuffles[i].sourceId}->{shuffles[i].targetId}");
                        if (shuffles.Count <= 0)
                        {
                            UIUtility.SetGlobalInteractive();
                            break;
                        }
                        if (m_SelectedItem != null)
                        {
                            m_SelectedItem.Select(false);
                            m_SelectedItem = null;
                        }
                        for (int i = 0; i < shuffles.Count; i++)
                        {
                            var shuffle = shuffles[i];
                            var item = m_Items[shuffle.sourceId];
                            item.Init(m_Level.items[shuffle.sourceId], m_Level.style, m_Level.layout, this);
                        }
                        UIUtility.SetGlobalInteractive();
                    }
                    else
                        UIUtility.DisplayPanel(ShufflePanle.ShufflePanleView.PANEL_KEY, "UI/Item/ShufflePanle/Prefabs/ShufflePanel", data: this);
                    break;
                case GamePanelNotifications.AddTimeBtn_CTRL:
                    LogManager.Log($"增加时间");
                    if (GameDataMgr.Instance.AddTimeRemainCount > 0)
                    {
                        m_Level.remainSeconds += BaseDataMgr.Instance.Cfg.props.time.seconds;
                        GameDataMgr.Instance.AddTimeRemainCount = GameDataMgr.Instance.AddTimeRemainCount - 1;
                    }
                    else
                        UIUtility.DisplayPanel(AddTimePanel.AddTimePanelView.PANEL_KEY, "UI/Item/AddTimePanel/Prefabs/AddTimePanel", data: this);
                    break;
            }
        }

        protected override void ClickToggleHandle(string name, bool isOn)
        {
            if (!isOn)
                UIUtility.DisplayPanel(PausePanel.PausePanelView.PANEL_KEY, "UI/PausePanel/Prefabs/PausePanel", data: this);
        }

        private void ShowBombEff(Item item)
        {
            var obj = PoolManager.Instance.Get(GamePanelNotifications.BOMB_ITEM_POOL);
            obj.transform.SetParent(transform);
            var rect = obj.transform as RectTransform;
            rect.anchoredPosition3D = Vector3.zero;

            var screen = Camera.main.WorldToScreenPoint(GetControl<Button>(GamePanelNotifications.BombBtn_CTRL).transform.position);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(transform as RectTransform, screen, Camera.main, out var pos);
            rect.anchoredPosition = pos;
            rect.GetComponent<BombAnim>().Init(item);
        }

        private IEnumerator DelayCreateItem()
        {
            float maxWidth = m_UILayout.sizeDelta.x;
            float maxHeight = m_UILayout.sizeDelta.y;

            // 修改预设尺寸
            var cellSize = CalculateGrid(m_Level.GetTotalRow(), m_Level.GetTotalCol());

            for (int i = 0; i < m_Level.items.Count; i++)
            {
                var itemObj = PoolManager.Instance.Get(GamePanelNotifications.ITEM_POOL);
                itemObj.transform.SetParent(m_UILayout.transform);

                var rect = itemObj.transform as RectTransform;
                rect.anchorMin = Vector2.zero;
                rect.anchorMax = Vector2.zero;
                rect.anchoredPosition3D = Vector3.zero;
                itemObj.transform.localScale = Vector3.one;
                rect.sizeDelta = new Vector2(cellSize.width, cellSize.height);

                // 总行数和总列数
                int rowCount = m_Level.GetTotalRow();
                int colCount = m_Level.GetTotalCol();

                // 计算当前格子的行号和列号
                int row = i / colCount;
                int col = i % colCount;

                // 计算当前格子的位置
                float x = m_Padding.left + col * (cellSize.width + m_Space) + cellSize.width * rect.pivot.x;
                float y = m_Padding.top + (rowCount - row - 1) * (cellSize.height + m_Space) + cellSize.height * rect.pivot.y;
                rect.anchoredPosition = new Vector2(x, y);

                var item = itemObj.GetComponent<Item>();
                item.Init(m_Level.items[i], m_Level.style, m_Level.layout, this);
                m_Items.Add(item);
                yield return null;
            }

            ResumeGame();

            // 新手引导检查
            m_Guide.Cache(m_Level);
        }

        // 计算格子尺寸
        private (float width, float height) CalculateGrid(int rows, int columns)
        {
            // 计算可用区域（减去Padding）
            float availableWidth = m_UILayout.sizeDelta.x - m_Padding.left - m_Padding.right;
            float availableHeight = m_UILayout.sizeDelta.y - m_Padding.top - m_Padding.bottom;

            // 计算格子大小（考虑固定间距）
            // 横向：columns个格子 + (columns-1)个间距
            float cellWidth = (availableWidth - (columns - 1) * m_Space) / columns;

            // 纵向：rows个格子 + (rows-1)个间距
            float cellHeight = (availableHeight - (rows - 1) * m_Space) / rows;

            // 返回结果（只返回格子宽高）
            return (cellWidth, cellHeight);
        }

        private bool m_IsPlayedMusic;
        private void Update()
        {
            if (GameDataMgr.Instance.IsUnlockTimeLimit() && m_PauseBtn.isOn)
            {
                m_Level.remainSeconds -= Time.deltaTime;
                var ts = System.TimeSpan.FromSeconds(m_Level.remainSeconds);
                GetControl<Text>(GamePanelNotifications.Time_CTRL).text = ts.ToString("mm\\:ss");

                if (m_Level.remainSeconds <= 4 && !m_IsPlayedMusic)
                {
                    m_IsPlayedMusic = true;
                    AudioManager.Instance.PlayAudio("Audios/Countdown4s");
                }

                if (m_Level.remainSeconds <= 0)
                {
                    // 游戏失败
                    UIUtility.DisplayPanel(LevelFailurePanel.LevelFailurePanelView.PANEL_KEY, "UI/LevelFailurePanel/Prefabs/LevelFailurePanel", data: this);
                }
            }
        }

        private void ClearItems()
        {
            foreach (var item in m_Items)
            {
                item?.Clear();
                PoolManager.Instance.Delete(GamePanelNotifications.ITEM_POOL, item.gameObject);
            }
            m_Items.Clear();
            PauseGame();
        }

        private void OnDisable()
        {
            ClearItems();
            if (GameDataMgr.Instance.IsUnlockErrorLimit())
                EventCenter.Instance.RemoveEventListen<int>(GameEventName.OnLifeCountChanged, OnLifeCountChanged);
        }

        public override void Hide(bool isDestroy = false)
        {
            base.Hide(isDestroy);
            GameDataMgr.Instance.Save();
        }

        public void SelctItem(Item item)
        {
            if (m_SelectedItem == null)
            {
                if (GameDataMgr.Instance.VibrationSwitch)
                    NativeInteraction.Instance.TriggerVibration(VibrationType.Soft);
                m_SelectedItem = item;
                item.Select();
                if (m_Hint1 != null && m_Hint2 != null)
                {
                    m_Hint1.DisplayHint(false);
                    m_Hint2.DisplayHint(false);
                    m_Hint1 = null;
                    m_Hint2 = null;
                }
            }
            else
            {
                if (m_SelectedItem == item)
                {
                    if (GameDataMgr.Instance.VibrationSwitch)
                        NativeInteraction.Instance.TriggerVibration(VibrationType.Soft);
                    m_SelectedItem.Select(false);
                    m_SelectedItem = null;
                    return;
                }

                // 计算是否可以消除
                var path = m_PathFinder.FindPath(m_SelectedItem.Data, item.Data, m_Level);
                if (path == null)
                {
                    if (GameDataMgr.Instance.VibrationSwitch)
                        NativeInteraction.Instance.TriggerVibration(VibrationType.Error);
                    AudioManager.Instance.PlayAudio("Audios/PlayError");
                    m_SelectedItem.Select(false);
                    m_SelectedItem = null;
                    // 不能消除，操作错误
                    m_Level.UpdateLifeRemainNum(-1);
                }
                else
                {
                    UIUtility.SetGlobalInteractive(false);
                    item.Select();
                    // 可以消除，这里可以消除两个格子
                    // 画线
                    m_Path.Clear();
                    for (int i = 0; i < path.Count; i++)
                        m_Path.Add((m_Items[path[i]].transform as RectTransform).anchoredPosition);
                    m_LineRenderer.DrawLine(m_Path, complate: isComplate => StartCoroutine(DelayDestroyItem(item)));
                }
            }
        }

        // 延迟消除
        [SerializeField] float m_DestroyDelay = .1f;
        private IEnumerator DelayDestroyItem(Item item)
        {
            yield return new WaitForSeconds(m_DestroyDelay);
            m_SelectedItem.Select(false);
            item.Select(false);

            if (GameDataMgr.Instance.VibrationSwitch)
                NativeInteraction.Instance.TriggerVibration(VibrationType.Success);
            AudioManager.Instance.PlayAudio("Audios/PlayMatch");
            m_SelectedItem.DisplayDestroyAnim();
            item.DisplayDestroyAnim();

            var item1Neighbors = m_Level.DestroyItem(m_SelectedItem.Data);
            var item2Neighbors = m_Level.DestroyItem(item.Data);

            StartCoroutine(InitNeighbors(item1Neighbors));
            StartCoroutine(InitNeighbors(item2Neighbors));

            m_LineRenderer.ClearLine();
            m_SelectedItem = null;

            yield return new WaitForSeconds(.25f);
            UIUtility.SetGlobalInteractive();
            // 检查是否胜利
            if (m_Level.IsLevelWin())
            {
                if (UIUtility.GetPanelState(HallPanel.HallPanelView.PANEL_KEY) != PanelState.Show)
                    UIUtility.DisplayPanel(HallPanel.HallPanelView.PANEL_KEY, "UI/HallPanel/Prefabs/HallPanel");
                PauseGame();
                var data = new object[3];
                data[0] = m_Level;
                // 星星数量，这里直接写死，因为UI设计最大3颗星
                data[1] = GetControl<Image>(GamePanelNotifications.ImgBg_CTRL).sprite;
                if (m_Level.status != ELevelStatus.Completed)
                {
                    m_Level.status = ELevelStatus.Completed;
                    GameDataMgr.Instance.CurLevel++;
                }
                UIUtility.DisplayPanel(LevelWinSettlePanel.LevelWinSettlePanelView.PANEL_KEY, "UI/LevelWinSettlePanel/Prefabs/LevelWinSettlePanel", data: data);
                UIUtility.HidePanel(PANEL_KEY);
            }
        }

        private IEnumerator InitNeighbors(List<int> neighborsId)
        {
            if (neighborsId.Count <= 0) yield break;
            for (int i = 0; i < neighborsId.Count; i++)
            {
                m_Items[neighborsId[i]].UpdateUIStatus();
            }
        }

        public void Restart()
        {
            m_IsPlayedMusic = false;
            m_Level.InitItems();
            ClearItems();
            StartCoroutine(DelayCreateItem());
            ResumeGame();
        }

        // 暂停游戏
        public void PauseGame()
        {
            m_PauseBtn.SetIsOnWithoutNotify(false);
        }

        // 继续游戏
        public void ResumeGame()
        {
            m_PauseBtn.isOn = true;
        }

        // 复活
        public void Revive()
        {
            m_IsPlayedMusic = false;
            m_Level.UpdateLifeRemainNum(3);
            ResumeGame();
        }

        // 暗示
        public bool Hint()
        {
            if (m_Hint1 != null || m_Hint2 != null) return true;
            var hintInfo = m_Level.FindCanDestroyTwoItems(m_PathFinder);
            if (hintInfo.id1 == -1 || hintInfo.id2 == -1) return false;
            if (m_SelectedItem != null)
            {
                m_SelectedItem.Select(false);
                m_SelectedItem = null;
            }
            m_Hint1 = m_Items[hintInfo.id1];
            m_Hint2 = m_Items[hintInfo.id2];
            m_Hint1.DisplayHint();
            m_Hint2.DisplayHint();
            return true;
        }
    }
}